/*
 * @(#)ObserverSwarm.java			0.1 21/11/2010
 * Copyright (C) 2010 Grupo de Alunos abaixo
 * 
 * Universidade Federal do ABC
 * Vida Artificial - 3o quadrimestre de 2010
 * Aluno: Abner
 * Aluno: Cláudio Antônio Peanho
 * Aluno: Fabrizio Borelli
 * Aluna: Maitê Balhester
 * Aluno: Rafael Munhoz
 * Professora Dr. Karla Vittori
 * Projeto: Simulação de Colônia de Formigas (antcolonyswarm)
 * 
 * Código baseado em jheatbugs-3.0 de Timothy Howe
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package br.edu.ufabc.va.acs.controller;

import java.util.List;

import br.edu.ufabc.va.acs.model.ModelSwarm;
import br.edu.ufabc.va.acs.model.agent.Ant;

import swarm.Selector;

import swarm.activity.ActionGroup;
import swarm.activity.ActionGroupImpl;
import swarm.activity.Activity;
import swarm.activity.Schedule;
import swarm.activity.ScheduleImpl;
import swarm.defobj.Zone;
import swarm.gui.Colormap;
import swarm.gui.ColormapImpl;

import swarm.gui.ZoomRaster;
import swarm.gui.ZoomRasterImpl;
import swarm.objectbase.Swarm;
import swarm.simtoolsgui.GUISwarmImpl;
import swarm.space.Object2dDisplay;
import swarm.space.Object2dDisplayImpl;
import swarm.space.Value2dDisplay;
import swarm.space.Value2dDisplayImpl;

/**
 * 
 * Controla a simulação (model) e apresentação na tela.
 * 
 * @author Peanho
 * 
 */
public class ObserverSwarm extends GUISwarmImpl {

	/** titulo da janela da simulação */
	private final String		windowTitle			= "Ant Colony Swarm";

	/** número de passos decorridos da simulação para exibição do estado */
	public int					displayFrequency	= 1;

	/** taxa de zoom da visualização da simulação */
	public int					zoomFactor			= 10;

	/** modelo da simulação */
	private final ModelSwarm	model;

	/** agenda a exibição da simulação */
	private Schedule			displaySchedule;

	/** widget de exibição da simulação */
	private ZoomRaster			worldRaster;

	/** mapa de cores dos elementos no ambiente */
	private Colormap			colormap;

	// /** mapa de figuras dos elementos do ambiente */
	// private Pixmap pixmap;

	/** representação gráfica das formigas */
	private Object2dDisplay		antDisplay;

	/** representação das intensiadades de feromônio na grade */
	private Value2dDisplay		pheromoneDisplay;

	/**
	 * Constrói e incializa uma instância com espaço de memória {@code zone}
	 * 
	 * @param zone
	 *            área de memória alocada pelo código objc.
	 */
	public ObserverSwarm(Zone zone) {
		super(zone);
		model = new ModelSwarm(getZone());

	}

	@Override
	public Object buildObjects() {
		super.buildObjects();

		/* para a simulação até o usuário clicar em start */
		getControlPanel().setStateStopped();

		/* permite ao modelo alocar seus objetos */
		model.buildObjects();

		/* cria um mapa de cores */
		colormap = new ColormapImpl(getZone());

		/*
		 * aloca tons de verde [0..63] para comida, vermelho[64..127] para
		 * feromônio
		 */
		for (double i = 0; i < 64; i++) {
			colormap.setColor$ToRed$Green$Blue((byte) i, i / 63, 0, 0);
			colormap.setColor$ToRed$Green$Blue((byte) (i + 64), 1, i / 63, 1.0);
		}

		/* aloca cinza 0.5 para obstáculos */
		// colormap.setColor$ToRed$Green$Blue((byte) 200, 0.5, 0.5, 0.5);

		/* aloca cor azul para as formigas */
		colormap.setColor$ToRed$Green$Blue((byte) 201, 0.0, 0.0, 1.0);

		/* aloca cor amarelo para formigas retornando a colonia */
		colormap.setColor$ToRed$Green$Blue((byte) 202, 1.0, 1.0, 0.0);

		/* aloca cor verde para a colônia */
		colormap.setColor$ToRed$Green$Blue((byte) 203, 0.0, 1.0, 0.0);
		/* atribui o indice de cor a cada formiga */
		List<Ant> antList = model.getAntList();
		for (Ant ant : antList) {
			ant.setColorIndex((byte) 201);
		}

		/* cria janela de exibição da simulação */
		worldRaster = new ZoomRasterImpl(getZone(), "worldRaster");
		try {
			worldRaster.enableDestroyNotification$notificationMethod(this,
					new Selector(getClass(), "worldRasterDeath", false));
		} catch (Exception e) {
			System.err.println("Exception worldRasterDeath: " + e.getMessage());
		}
		worldRaster.setColormap(colormap);
		worldRaster.setZoomFactor(zoomFactor);
		worldRaster
				.setWidth$Height(model.getGridWidth(), model.getGridHeight());
		worldRaster.setWindowTitle(windowTitle);
		worldRaster.pack();

		/*
		 * cria um Value2dDisplay para exibir o espaço de feromônios no
		 * ZoomRaster
		 */
		pheromoneDisplay = new Value2dDisplayImpl(getZone(), worldRaster,
				colormap, model.getWorld().getPheromoneSpace());
		//pheromoneDisplay.setDisplayMappingM$C(512, 0);

		try {
			antDisplay = new Object2dDisplayImpl(getZone(), worldRaster, model
					.getWorld().getWorld(), new Selector(GraphicObject.class,
					"drawSelfOn", false));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.err.println("Falha na chamada ao método: " + e.getMessage());
		}

		antDisplay.setObjectCollection(model.getGraphicObjects());

		return this;
	}

	@Override
	public Object buildActions() {
		super.buildActions();

		model.buildActions();
		ActionGroup updateActions = new ActionGroupImpl(getZone());
		ActionGroup tkActions = new ActionGroupImpl(getZone());

		try {
			updateActions.createActionTo$message(this, new Selector(getClass(),
					"updateGUI", false));
			tkActions.createActionTo$message(getActionCache(), new Selector(
					getActionCache().getClass(), "doTkEvents", true));
		} catch (Exception e) {
			System.err.println("Exceção na atualização da simulação: "
					+ e.getMessage());
		}

		/* define o agendamento de ações na simulação */
		displaySchedule = new ScheduleImpl(getZone(), displayFrequency);

		displaySchedule.at$createAction(0, updateActions);

		displaySchedule.at$createAction(0, tkActions);
		return this;
	}

	/*
	 * (non-Javadoc) TODO adicionar Schedule para controle dos passos da
	 * simulação
	 * 
	 * @see swarm.simtoolsgui.GUISwarmImpl#activateIn(swarm.objectbase.Swarm)
	 */
	@Override
	public Activity activateIn(Swarm context) {
		super.activateIn(context);
		model.activateIn(this);
		displaySchedule.activateIn(this);
		return getActivity();
	}

	/**
	 * Finaliza a janela de exibição do ambiente.
	 * 
	 * @param caller
	 * @return
	 */
	public Object worldRasterDeath(Object caller) {
		worldRaster.drop();
		worldRaster = null;
		return this;
	}

	/**
	 * Atualiza a exibição da simulação.
	 * 
	 * @return this
	 */
	public Object updateGUI() {
		if (worldRaster != null) {
			pheromoneDisplay.display();
			antDisplay.display();
			worldRaster.drawSelf();
		}
		return this;
	}

}
